<?php

/* ========================================================================= */
/* This file is part of the HypnoPHP Framework Library                       */
/* Copyright (c) 2009-2010, Radu Buzea                                       */
/* ========================================================================= */

/**
* @author Radu Buzea
* @copyright Copyright (c) 2009-2010, Radu Buzea (www.hypnosis.ro)
* @license GNU Lesser General Public License (www.gnu.org/copyleft/lesser.html)
* @package HypnoPHP
* @category Core
* @version 1.0.3
*/

defined('HYPNOPHP_APPLICATION') or
die("Cannot use <i>" . basename(__FILE__) . "</i> outside HypnoPHP Application");

// ============================================================================
// Final class: HFactory
// ============================================================================

final class HFactory
{

	/**
	* This function is not an implementation of the Factory design pattern. The function
	* receives the name of the class, then it search and includes a script file that contains
	* the class. This method is called from the '__autoload' magic function.
	*
	* @param string $class_name The class name
	* @return bool
	*/
	public static function loader($class_name = '')
	{
		$test = class_exists($class_name, false);
		if ($test) { return true; }
		global $_HAPPLICATION_PATHS, $_HAPPLICATION_ROOT_PATH;
		$result = false;
		$is = 'none';
		$paths = array();

		$p = strpos($class_name, 'Module_');
		if ($p !== false && $p == 0) { $is = 'module'; }
		if ($is == 'none') {
			$p = strpos($class_name, 'Controller_');
			if ($p !== false && $p == 0) { $is = 'controller'; }
		}
		if ($is == 'none') {
			$p = strpos($class_name, 'Model_');
			if ($p !== false && $p == 0) { $is = 'model'; }
		}
		if ($is == 'none') {
			$p = strpos($class_name, 'Helper_');
			if ($p !== false && $p == 0) { $is = 'helper'; }
		}

		switch ($is) {
			case 'module':
				if (isset($_HAPPLICATION_PATHS['app_modules'])) { $paths[] = $_HAPPLICATION_PATHS['app_modules']; }
				if (isset($_HAPPLICATION_PATHS['system_modules'])) { $paths[] = $_HAPPLICATION_PATHS['system_modules']; }
				$file_name = str_replace(array('Module_', '_'), array('', DS), $class_name);
				break;
			case 'controller':
				if (isset($_HAPPLICATION_PATHS['app_controllers'])) { $paths[] = $_HAPPLICATION_PATHS['app_controllers']; }
				$file_name = str_replace(array('Controller_', '_'), array('', DS), $class_name);
				break;
			case 'model':
				if (isset($_HAPPLICATION_PATHS['app_models'])) { $paths[] = $_HAPPLICATION_PATHS['app_models']; }
				$file_name = str_replace(array('Model_', '_'), array('', DS), $class_name);
				break;
			case 'helper':
				if (isset($_HAPPLICATION_PATHS['app_helpers'])) { $paths[] = $_HAPPLICATION_PATHS['app_helpers']; }
				if (isset($_HAPPLICATION_PATHS['system_helpers'])) { $paths[] = $_HAPPLICATION_PATHS['system_helpers']; }
				$file_name = str_replace(array('Helper_', '_'), array('', DS), $class_name);
				break;
			default:
				if (isset($_HAPPLICATION_PATHS['system_lib'])) { $paths[] = $_HAPPLICATION_PATHS['system_lib']; }
				else if (defined('HSYSTEM_LIB_PATH')) { $paths[] = HSYSTEM_LIB_PATH; }
				else { $paths[] = realpath(dirname(__FILE__)); }
				$file_name = str_replace('_', DS, $class_name);
		}
		foreach ($paths as $path) {
			$inc_file_name = $path . DS . $file_name . '.php';
			if (is_file($inc_file_name)) {
				include $inc_file_name;
				$result = class_exists($class_name, false);
				if ($result) { break; }
			}
		}
		return $result;
	}

	/**
	* This function is an implementation of the Factory design pattern that allows for
	* the instantiation of objects at runtime. The function receives the name of the
	* class to instantiate as argument.
	*
	* @param string $class_name The class name
	* @param bool $trigger_error Optional parameter (default TRUE)
	* @return bool
	*/
	public static function factory($class_name = '', $trigger_error = true)
	{
		if (!self::loader($class_name)) {
			if ($trigger_error) {
				trigger_error("Unable to load the class <i>{$class_name}</i> and to instantiate an object ",
					E_USER_ERROR);
			}
			return null;
		}
		return new $class_name();
	}

}

# ###########################################################################

/**
* This function is automatically called for undefined classes and/or interfaces.
* This is a magic function implemented in PHP5.
*
* @param string $class_name
* @return void
*/
function __autoload($class_name = '')
{
	if (!HFactory::loader($class_name)) {
		if ($class_name == 'HPrettyUI') { return; }
		trigger_error("Unable to load the class <i>{$class_name}</i> ", E_USER_ERROR);
	}
}

# ###########################################################################